package cn.chengpengper.im.platform.common.risk.rule.service.impl;

import cn.chengpengper.im.platform.common.model.enums.HttpCode;
import cn.chengpengper.im.platform.common.risk.enums.RuleEnum;
import cn.chengpengper.im.platform.common.risk.rule.service.RuleChainService;
import cn.chengpengper.im.platform.common.risk.rule.service.base.BaseRuleChainService;
import cn.chengpengper.im.platform.common.risk.window.SlidingWindowLimitService;
import cn.hutool.core.util.BooleanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/*@formatter:off*/

/**
 * ____________________
 * < 神兽护体，永无bug! >
 * --------------------
 *
 * @author huchengpeng
 * @version v1.0.0
 * @date 2024/11/23 21:26
 * @description IP 限流拦截器
 */

/*@formatter:on*/

@Slf4j
@Component
public class IpRuleChainService extends BaseRuleChainService implements RuleChainService {

    private static final int DEFAULT_WINDOWS_SIZE = 50;
    private static final int DEFAULT_WINDOWS_PERIOD = 1000;

    @Value("${diy.im.rule.ipRule.enabled}")
    private Boolean ipRuleEnabled;

    @Value("${diy.im.rule.ipRule.order}")
    private Integer ipRuleOrder;
    /**
     * 滑动窗口大小
     */
    @Value("${diy.im.rule.ipRule.windowsSize}")
    private Integer windowsSize;
    /**
     * 限流窗口的周期
     */
    @Value("${diy.im.rule.ipRule.windowPeriod}")
    private Long windowPeriod;

    @Autowired
    private SlidingWindowLimitService slidingWindowLimitService;

    @Override
    public HttpCode execute(HttpServletRequest request, Object handler) {
        if (BooleanUtil.isFalse(ipRuleEnabled)) {
            return HttpCode.SUCCESS;
        }
        try {
            windowsSize = Objects.isNull(windowsSize) ? DEFAULT_WINDOWS_SIZE : windowsSize;
            windowPeriod = Objects.isNull(windowPeriod) ? DEFAULT_WINDOWS_PERIOD : windowPeriod;
            String ip = getIp(request);
            boolean result = slidingWindowLimitService.passThough(ip, windowPeriod, windowsSize);
            return result ? HttpCode.SUCCESS : HttpCode.PARAMS_ERROR;
        } catch (Exception e) {
            log.error("IpRuleChainService | IP 限制异常:{}", e.getMessage());
            return HttpCode.PARAMS_ERROR;
        }
    }

    @Override
    public int getOrder() {
        return Objects.isNull(ipRuleOrder) ? RuleEnum.IP.getCode() : ipRuleOrder;
    }

    @Override
    protected String getServiceName() {
        return RuleEnum.IP.getMesaage();
    }
}
